package com.zwt.redis;



import com.zwt.util.TTime;
import com.zwt.util.sms.MessageUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.util.Asserts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.SerializationUtils;
import redis.clients.jedis.*;

import java.util.Date;
import java.util.Random;

public class TRedis {
    private static final JedisPool pool;

    private static final String DEFAULT_HOST = "192.168.0.244";
    private static final String DEFAULT_PASSWD = "123456";
    private static final String DEFAULT_PORT = "6379";

    private static final Logger log = LoggerFactory.getLogger(MessageUtil.class);

    @Value("${spring.redis.host}")
    private static String host;

    @Value("${spring.redis.port}")
    private static int port;

    @Value("${spring.redis.password}")
    private static String password;

    static {
        final JedisPoolConfig config = new JedisPoolConfig();
        //最大空闲连接数, 应用自己评估，不要超过AliCloudDB for Redis每个实例最大的连接数
        config.setMaxIdle(200);
        //最大连接数, 应用自己评估，不要超过AliCloudDB for Redis每个实例最大的连接数
        config.setMaxTotal(300);
        config.setTestOnBorrow(false);
        config.setTestOnReturn(false);
        /*String host = ConfigProperty.getProperty("redis.host", DEFAULT_HOST);
        String password = ConfigProperty.getProperty("redis.password", DEFAULT_PASSWD);
        Integer port = Integer.parseInt(ConfigProperty.getProperty("redis.port", DEFAULT_PORT));*/
        pool = new JedisPool(config, host, port, 3000, password);
//        pool = new JedisPool(config, "115.28.66.66", 6379, 3000, "taiHe123");
        Asserts.notNull(pool, "JedisPool is null , please check config!");
    }

    private static String getKeyName(String region, Object key) {
        if (key instanceof Number) {
            return region + ":I:" + key;
        } else {
            @SuppressWarnings("rawtypes")
            Class keyClass = key.getClass();
            if (String.class.equals(keyClass)
                    || StringBuffer.class.equals(keyClass)
                    || StringBuilder.class.equals(keyClass)) {
                return region + ":S:" + key;
            }
        }
        return region + ":O:" + key;
    }

    public static Object get(String cacheKey, Object key) {
        return get(getKeyName(cacheKey, key));
    }

    public static long getTTL(String key) {
        try {
            return getJedis().ttl(key);
        } catch (Exception e) {
            log.error("get ttl Exception, ", e);
            e.printStackTrace();
        }
        return -1;
    }



    public static void main(String[] args) {
        System.out.println(getStr("BANK_CARD_HINT_15201341671"));
//        setStr("aa", "aa", 10000);
//        setStr("aa", "aa", -10);

//		put("login_tAgrees_1",
//				"login_tAgrees_1",null,1);
//		put("login_tAgrees_2",
//				"login_tAgrees_2",null,1);
//		put("login_tAgrees_3",
//						"login_tAgrees_3",null,1);
//		put("test", "11", "hah2a");
//		System.out.println(get("test", "11"));
//		String key="aaa";
//		lPushStr(key, 11+"");
//		lPushStr(key, 22+"");
//		lPushStr(key, 33+"");
//		System.out.println(rPopStr(key));
//		System.out.println(rPopStr(key));
//		System.out.println(rPopStr(key));
//		System.out.println(rPopStr(key)==null);

//		incr("sss",60);
//		System.out.println(incr("sss",60));
        //以下是对 set集合的测试
        //新增
//		String key = "set_test";
//		String[] a1 = {"1","2","3","4","5","6","7","8","9","2"};
//		System.out.println(sAdd(key, a1));
//		System.out.println("长度"+scard(key));
//		for(int i=0;i<2000;i++){
//			String[] a2 = {"1"+i,"aa"+i,"bb"+i,"cc"+i};
//			System.out.println(sAdd(key, a2));
//		}
//		System.out.println("长度"+scard(key));
//		//遍历取数据
//		String cusor = "0";
//		while(true){
//			 ScanResult<String> sr = sScan(key, cusor,198);
//			 if(sr != null){
//				 List<String> ss = sr.getResult();
//				 System.out.println(ss+"  "+ss.size());
//				 System.out.println(sr.getStringCursor());
//				 cusor =sr.getStringCursor();
//				 if("0".equals(cusor)){
//					 break;
//				 }
//			 }
//			
//		}
//		//删除集合
//		del(key);


//    	System.out.println(TString.formatDecimals("111","0",0));
//    	Set<String> aa = new HashSet<String>();
//    	for(int i=0;i<10000;i++){
//    		String ss = generateTimeKey()+"";
//    		aa.add(ss);
//    		System.out.println(ss+  "   "+i);
//    	}
//    	System.out.println(aa.size());
    }

    /**
     * 根据时间生成key  最快每秒支持万级别 99999
     *
     * @return 20170418000001   前十位是时间,后五位是该小时的第几个申请单
     */
    public static long generateTimeKey() {
        final Random random = new Random();
        String dateStr = TTime.parseStringFromDate(new Date(), "yyMMddHH");
        String numberKey = "";
        while (StringUtils.isBlank(numberKey)) {
            numberKey = dateStr + (random.nextInt(99999) % (99999 - 10000 + 1) + 10000);
            String key = "apply_key_" + numberKey;
            long index = TRedis.incr(key, 60 * 60);
            if (index > 1) {
                numberKey = "";
            }
        }
        return Long.parseLong(numberKey);
    }

    public static Object get(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Object obj = null;
        try (Jedis jedis = getJedis()) {
            byte[] b = jedis.get(SerializationUtils.serialize(key));
            if (b != null) {
                obj = SerializationUtils.deserialize(b);
            }
        } catch (Exception e) {
            log.error("Error occured when get data from redis thre key is " + key, e);
            e.printStackTrace();
        }
        return obj;
    }


    /**
     * 获取set集合的大小
     *
     * @param key
     * @return
     */
    public static Long scard(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Long str = null;
        try (Jedis jedis = getJedis()) {
            str = jedis.scard(key);
        } catch (Exception e) {
            log.error("Error occured when scard redis thre key is " + key, e);
        }
        return str;
    }

    /**
     * 向set添加值
     *
     * @param key
     * @return 被添加到集合中的新元素的数量，不包括被忽略的元素。
     */
    public static Long sAdd(String key, String[] members) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Long str = null;
        try (Jedis jedis = getJedis()) {
            str = jedis.sadd(key, members);
        } catch (Exception e) {
            log.error("Error occured when sAdd redis thre key is " + key, e);
        }
        return str;
    }

    /**
     * 从set集合中便利数据
     *
     * @param key
     * @return 其中  getResult()获取集合列表  getStringCursor() 获取下次集合的起始位置
     */
    public static ScanResult<String> sScan(String key, String cursor, int pageSize) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        ScanResult<String> str = null;
        try (Jedis jedis = getJedis()) {
            ScanParams sp = new ScanParams();
            sp.count(pageSize);
            str = jedis.sscan(key, cursor, sp);
        } catch (Exception e) {
            log.error("Error occured when sScan redis thre key is " + key, e);
            e.printStackTrace();
        }
        return str;
    }

    /**
     * @param key
     * @return
     */
    public static Long lPushStr(String key, String movieId) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Long str = null;
        try (Jedis jedis = getJedis()) {
            str = jedis.lpush(key, movieId);
        } catch (Exception e) {
            log.error("Error occured when lPushStr from redis thre key is " + key, e);
        }
        return str;
    }

    /**
     * @param key
     * @return
     */
    public static String rPopStr(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        String str = null;
        try (Jedis jedis = getJedis()) {
            str = jedis.rpop(key);
        } catch (Exception e) {
            log.error("Error occured when rPopStr from redis thre key is " + key, e);
            e.printStackTrace();
        }
        return str;
    }

    /**
     * @param key
     * @return
     */
    public static String getStr(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        String str = null;
        try (Jedis jedis = getJedis()) {
            str = jedis.get(key);
        } catch (Exception e) {
            log.error("Error occured when getStr from redis thre key is " + key, e);
            e.printStackTrace();
        }
        return str;
    }

    /**
     * @param key
     * @param value
     * @param seconds 过期时间  如果不舍，小于0即可
     * @return
     */
    public static String setStr(String key, String value, int seconds) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        String str = null;
        try (Jedis jedis = getJedis()) {
            if (seconds > 0) {
                str = jedis.setex(key, seconds, value);
            } else {
                str = jedis.set(key, value);
            }

        } catch (Exception e) {
            log.error("Error occured when setStr from redis thre key is " + key, e);
            e.printStackTrace();
        }
        return str;
    }

    /**
     * @param key           自增主键
     * @param expriseSecond 过期时间
     * @return
     */
    public static long incr(String key, int expriseSecond) {
        long index = -1;
        if (StringUtils.isBlank(key)) {
            return index;
        }
        try (Jedis jedis = getJedis()) {
            index = jedis.incr(key);
            if (expriseSecond > 0) {
                jedis.expire(key, expriseSecond);
            }
        } catch (Exception e) {
            log.error("Error occured when incr from redis thre key is " + key, e);
            e.printStackTrace();
        }
        return index;
    }

    public static void put(String cacheKey, Object key, Object value) {
        if (value == null) {
            remove(cacheKey, key);
        } else {
            try (Jedis jedis = getJedis()) {
                jedis.set(SerializationUtils.serialize(getKeyName(cacheKey, key)),
                        SerializationUtils.serialize(value));
            } catch (Exception e) {
                log.error("Error occured when put data to redis" + key, e);
                e.printStackTrace();
            }
        }
    }

    public static void put(String cacheKey, Object key, Object value, int expriseSecond) {
        if (value == null) {
            remove(cacheKey, key);
        } else {
            try (Jedis jedis = getJedis()) {
                jedis.setex(SerializationUtils.serialize(getKeyName(cacheKey, key))
                        , expriseSecond, SerializationUtils.serialize(value));
            } catch (Exception e) {
                log.error("Error occured when put data to redis" + key, e);
                e.printStackTrace();
            }
        }
    }

    public static void remove(String region, Object key) {
        String keys = getKeyName(region, key);
        remove(keys);
    }

    public static void del(String key) {
        try (Jedis jedis = getJedis()) {
            jedis.del(key);
        } catch (Exception e) {
            log.error("Error occured when remove data from redis key is" + key, e);
            e.printStackTrace();
        }
    }

    private static Jedis getJedis() {
        Jedis jedis = pool.getResource();
        Asserts.notNull(jedis, "jedis");
        return jedis;
    }

    public static void remove(String key) {
        if (StringUtils.isBlank(key)) {
            return;
        }
        try (Jedis jedis = getJedis()) {
            jedis.del(SerializationUtils.serialize(key));
        } catch (Exception e) {
            log.error("Error occured when remove data from redis key is" + key, e);
            e.printStackTrace();
        }
    }
}
